# !/usr/bin/python2.7
# -*- coding: UTF-8 -*-

###/usr/lib/python2.7/curses
###https://www.rddoc.com/doc/Python-3.6.0/library/curses/

import os
import sys
import time
import curses
import locale
import thread

exitflag = False

def displaysize():
    (screen_rows, screen_columns) = os.popen('stty size', 'r').read().split()
    return int(screen_rows),int(screen_columns)

class mcurwin():
    def __init__(self,stdscr=None,hight=40,width=100,starty=0,startx=0):
        #支持中文显示
        locale.setlocale(locale.LC_ALL, "")
        code = locale.getpreferredencoding()
        #初始化　curses
        if not stdscr is None:
            self.stdscr = stdscr
        else:
            self.stdscr = curses.initscr()
        self.hight=hight
        self.width=width
        self.starty=starty
        self.startx=startx
        #获取终端可显示大小，(几行，几列)
        (screen_rows, screen_columns) = self.stdscr.getmaxyx()
        if screen_rows < self.hight or screen_columns < self.width:
            print "The interface is too small to display! Least 1366*768 or rows*columns > 40*100."
            curses.endwin()
            exit()
        #设置窗口大小
        self.stdscr = curses.newwin(self.hight,self.width,self.starty,self.startx)
        self.set_win()
        self.inputstr = ''
        self.scrbuff = ''
        self.dispbuff = ''

    def getdisplaysize(self):
        return self.hight,self.width,self.starty,self.startx

    def getscr(self):
        return self.stdscr

    def newsubwin(self,hight=20,width=50,starty=0,startx=0):
        subwin=mcurwin(self.stdscr,hight,width,starty+self.starty,startx+self.startx)
        return subwin

    def display_info(self,istr, x, y, colorpair=2):
        '''''使用指定的colorpair显示文字'''  
        istr=istr.replace('\r','')
        self.stdscr.addstr(y, x,istr, curses.color_pair(colorpair))
        self.stdscr.refresh()

    def vprint(self,istr,colorpair=2):
        istr=istr.replace('\r','')
        (y,x)=self.stdscr.getyx()
        strlen=len(istr)
        if (x+strlen) < self.width:
            self.stdscr.addstr(y, x,istr, curses.color_pair(colorpair))
            if self.stdscr.getyx()[0] >= (self.hight-1):
                self.stdscr.erase()
        else:
            self.stdscr.addstr(y,x,istr[0:(self.width-x)], curses.color_pair(colorpair))
            if self.stdscr.getyx()[0] >= (self.hight-1):
                self.stdscr.move(self.starty,self.startx)
                self.stdscr.erase()
            self.mprint(istr[(self.width-x):],colorpair)
        self.stdscr.refresh()
        return

    def mprint(self,istr,colorpair=2):
        (y,x)=self.stdscr.getyx()
        self.scrbuff=self.scrbuff+istr
        self.dispbuff=self.dispbuff+istr
        if (len(istr)+((y+istr.count('\n'))*self.width)) >= (self.hight*self.width):
            self.dispbuff=self.dispbuff[self.width:]
            self.stdscr.erase()
        self.display_info(self.dispbuff,0,0,colorpair)
        self.stdscr.refresh()
        return

    def savewin(self,filepath):
        name = os.path.basename(filepath)
        path = filepath.replace(name,'')
        if not os.path.exists(path):
            os.mkdir(path)
        with open(filepath,'w') as fo:
            fo.write(self.scrbuff)
        return True

    def progressbar(self,ps,x=0,y=0,width=50,colorpair=2,character='█'):
        ps=((ps>100) and 100 or ps)
        pss=int(ps/(100.0/width))
        self.display_info(('|'+pss*character+(width-pss)*' '+'| [%3d%%]'%(int(ps))),x,y,colorpair) 
        return 

    def get_ch_and_continue(self):
        '''''演示press any key to continue'''
        #设置nodelay，为0时会变成阻塞式等待
        self.stdscr.nodelay(0)
        #输入一个字符
        ch=self.stdscr.getch()
        #重置nodelay,使得控制台可以以非阻塞的方式接受控制台输入，超时1秒
        self.stdscr.nodelay(1)
        return True

    def get_str_keyboard(self,x=0,y=0): 
        self.stdscr.nodelay(1)
        ch = self.stdscr.getch()
        if ch == curses.KEY_UP:#↑
            return '↑'
        if ch == curses.KEY_DOWN:#↓
            return '↓'
        if ch == curses.KEY_RIGHT:#→
            return '→'
        if ch == curses.KEY_LEFT:#'←'
            return '←'
        if ch == curses.KEY_F5:#'←'
            return 'F5'
        if ch == curses.KEY_BACKSPACE:#'Backspace'
            self.display_info('%s' % (len(self.inputstr)*' '),x,y,1)
            self.inputstr = self.inputstr[:-1]
            self.display_info(self.inputstr,x,y,1)
            return False
        if ch == 27:
            return 'Esc'
        if ch == 24:
            return 'Ctrl+x'
        if ch == 5:
            return 'Ctrl+e'
        if ch == 2:
            return 'Ctrl+b'
        if ch == 0x0A or ch == 0x0D:
            #self.display_info('%s' % (len(mcurwin.inputstr)*' '),x,y,1)
            if not self.inputstr:
                return 'Enter'
            instr = self.inputstr
            #mcurwin.inputstr = ''
            return instr
        elif ch < 128 and ch >= 0:
            self.inputstr = self.inputstr + chr(ch & 0x7f)
            self.display_info(self.inputstr,x,y,1)
        return False 

    def set_win(self,cursset=1):
        '''''控制台设置'''
        #使用颜色首先需要调用这个方法
        curses.start_color()
        #文字和背景色设置，设置了四个color pair，分别为1和2
        curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLACK)
        curses.init_pair(2, curses.COLOR_GREEN, curses.COLOR_BLACK)
        curses.init_pair(3, curses.COLOR_BLACK, curses.COLOR_GREEN)
        curses.init_pair(4, curses.COLOR_RED, curses.COLOR_WHITE)
        #0隐藏光标,1光标可见
        curses.curs_set(cursset)
        #关闭屏幕回显
        curses.noecho()
        #输入时不需要回车确认
        curses.cbreak()
        #使用键盘上一些特殊字符,会将方向、Fx等转换为特殊序列
        self.stdscr.keypad(1)
        #设置nodelay，使得控制台可以以非阻塞的方式接受控制台输入，超时1秒
        self.stdscr.nodelay(1)

    def unset_win(self):
        '''控制台重置'''
        #恢复控制台默认设置（若不恢复，会导致即使程序结束退出了，控制台仍然是没有回显的）
        self.stdscr.keypad(0)
        curses.nocbreak()
        curses.echo()
        #结束窗口
        curses.endwin()

def keyboard_thread(win,subwin,x,y):
    global exitflag
    while exitflag == False:
        instr=win.get_str_keyboard(x,y)
        if instr == False:
            continue
        if instr == 'Esc':
            exitflag=True
        elif 'savewin' in instr:
            if len(instr.split()) > 1:
                res = subwin.savewin(instr.split()[1])
            else:
                res = subwin.savewin(r'./winlog.log')
            if res:
                win.display_info('save success',0,2)
    return

def main():
    win=mcurwin()
    try:
        win.display_info('mcurwin show',0,0)
        subwin=win.newsubwin(hight=30,width=100,starty=10,startx=0)
        thread.start_new_thread(keyboard_thread,(win,subwin,0,1))
        i=0 
        while exitflag == False:
            subwin.mprint('%d abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%%^&*()+-=\r\n'%(i))
            win.progressbar(i%101,0,4,70,1,'#')
            time.sleep(0.1)
            i=i+1

        #win.getscr().clear()
        win.display_info('Press any key to continue...',0,5)
        win.get_ch_and_continue()

    except Exception,e:
        raise e
    finally:
        win.unset_win()  
    return

if __name__ == '__main__':
    main()
    exit()
    
